From 482d898333facf53bd3208cf5e44a0cf3e1f4f3b Mon Sep 17 00:00:00 2001
From: phunkyfish <phunkyfish@gmail.com>
Date: Thu, 8 Oct 2020 14:59:55 +0100
Subject: [PATCH] Use std::thread, std::mutex, condition_variable instead of
 event

Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
---
 src/lib/tsreader/DeMultiplexer.cpp   |  2 +-
 src/lib/tsreader/DeMultiplexer.h     |  4 +-
 src/lib/tsreader/FileReader.cpp      |  2 +-
 src/lib/tsreader/MemoryBuffer.cpp    | 15 +++--
 src/lib/tsreader/MemoryBuffer.h      |  7 +-
 src/lib/tsreader/MemoryReader.h      |  1 +
 src/lib/tsreader/MemorySink.cpp      |  2 +-
 src/lib/tsreader/MemorySink.h        |  4 +-
 src/lib/tsreader/MepoRTSPClient.cpp  | 28 ++++----
 src/lib/tsreader/MepoRTSPClient.h    | 10 ++-
 src/lib/tsreader/MultiFileReader.cpp |  9 ++-
 src/os-dependent.h                   | 95 ++++++++++++++++++++++++++++
 src/pvrclient-mediaportal.cpp        | 29 ++++-----
 src/pvrclient-mediaportal.h          | 21 +++---
 14 files changed, 168 insertions(+), 61 deletions(-)

diff --git a/src/lib/tsreader/DeMultiplexer.cpp b/src/lib/tsreader/DeMultiplexer.cpp
index 436e452..3d0d9a2 100644
--- a/src/lib/tsreader/DeMultiplexer.cpp
+++ b/src/lib/tsreader/DeMultiplexer.cpp
@@ -104,7 +104,7 @@ namespace MPTV
         if (m_filter.IsSeeking())
             return 0;       // Ambass : to check
 
-        P8PLATFORM::CLockObject lock(m_sectionRead);
+        std::lock_guard<std::mutex> lock(m_sectionRead);
         if (NULL == m_reader)
             return 0;
 
diff --git a/src/lib/tsreader/DeMultiplexer.h b/src/lib/tsreader/DeMultiplexer.h
index c7cd577..72ed87d 100644
--- a/src/lib/tsreader/DeMultiplexer.h
+++ b/src/lib/tsreader/DeMultiplexer.h
@@ -37,7 +37,7 @@
 #include "PacketSync.h"
 #include "TSHeader.h"
 #include "PatParser.h"
-#include "p8-platform/threads/mutex.h"
+#include <mutex>
 
 namespace MPTV
 {
@@ -60,7 +60,7 @@ namespace MPTV
     private:
         unsigned long long m_LastDataFromRtsp;
         bool m_bEndOfFile;
-        P8PLATFORM::CMutex m_sectionRead;
+        std::mutex m_sectionRead;
         FileReader* m_reader;
         CPatParser m_patParser;
         CTsReader& m_filter;
diff --git a/src/lib/tsreader/FileReader.cpp b/src/lib/tsreader/FileReader.cpp
index 73b23af..358b05f 100644
--- a/src/lib/tsreader/FileReader.cpp
+++ b/src/lib/tsreader/FileReader.cpp
@@ -35,7 +35,7 @@
 #include "FileReader.h"
 #include <kodi/General.h> //for kodi::Log
 #include "TSDebug.h"
-#include "p8-platform/threads/threads.h"
+#include "os-dependent.h"
 #include <algorithm> //std::min, std::max
 #include "utils.h"
 #include <errno.h>
diff --git a/src/lib/tsreader/MemoryBuffer.cpp b/src/lib/tsreader/MemoryBuffer.cpp
index 0e736f2..b5400da 100644
--- a/src/lib/tsreader/MemoryBuffer.cpp
+++ b/src/lib/tsreader/MemoryBuffer.cpp
@@ -29,7 +29,7 @@
 
 #ifdef LIVE555
 
-#include "p8-platform/threads/mutex.h"
+#include "os-dependent.h"
 #include "MemoryBuffer.h"
 #include <kodi/General.h> //for kodi::Log
 #include "TSDebug.h"
@@ -56,7 +56,7 @@ bool CMemoryBuffer::IsRunning()
 
 void CMemoryBuffer::Clear()
 {
-  P8PLATFORM::CLockObject BufferLock(m_BufferLock);
+  std::lock_guard<std::mutex> BufferLock(m_BufferLock);
   std::vector<BufferItem *>::iterator it = m_Array.begin();
 
   for (auto& item : m_Array)
@@ -104,14 +104,17 @@ size_t CMemoryBuffer::ReadFromBuffer(unsigned char *pbData, size_t lDataLength)
   {
     if (!m_bRunning)
       return 0;
-    m_event.Wait(5000);
+
+    std::unique_lock<std::mutex> lock(m_BufferLock);
+    m_condition.wait_for(lock, std::chrono::milliseconds(5000));
+
     if (!m_bRunning)
       return 0;
   }
 
   // kodi::Log(ADDON_LOG_DEBUG, "get..%d/%d", lDataLength, m_BytesInBuffer);
   size_t bytesWritten = 0;
-  P8PLATFORM::CLockObject BufferLock(m_BufferLock);
+  std::lock_guard<std::mutex> BufferLock(m_BufferLock);
 
   while (bytesWritten < lDataLength)
   {
@@ -172,7 +175,7 @@ long CMemoryBuffer::PutBuffer(unsigned char *pbData, size_t lDataLength)
   memcpy(item->data, pbData, lDataLength);
   bool sleep = false;
   {
-    P8PLATFORM::CLockObject BufferLock(m_BufferLock);
+    std::lock_guard<std::mutex> BufferLock(m_BufferLock);
     m_Array.push_back(item);
     m_BytesInBuffer += lDataLength;
 
@@ -192,7 +195,7 @@ long CMemoryBuffer::PutBuffer(unsigned char *pbData, size_t lDataLength)
     }
     if (m_BytesInBuffer > 0)
     {
-      m_event.Broadcast();
+      m_condition.notify_one();
     }
   }
 
diff --git a/src/lib/tsreader/MemoryBuffer.h b/src/lib/tsreader/MemoryBuffer.h
index 080553b..4f8708f 100644
--- a/src/lib/tsreader/MemoryBuffer.h
+++ b/src/lib/tsreader/MemoryBuffer.h
@@ -30,7 +30,8 @@
 
 #ifdef LIVE555
 
-#include "p8-platform/threads/mutex.h"
+#include <condition_variable>
+#include <mutex>
 #include <vector>
 
 class CMemoryBuffer
@@ -55,9 +56,9 @@ class CMemoryBuffer
 
   protected:
     std::vector<BufferItem *> m_Array;
-    P8PLATFORM::CMutex m_BufferLock;
+    std::mutex m_BufferLock;
     size_t    m_BytesInBuffer;
-		P8PLATFORM::CEvent m_event;
+    std::condition_variable m_condition;
     bool m_bRunning;
 };
 #endif //LIVE555
diff --git a/src/lib/tsreader/MemoryReader.h b/src/lib/tsreader/MemoryReader.h
index fef4f98..288984b 100644
--- a/src/lib/tsreader/MemoryReader.h
+++ b/src/lib/tsreader/MemoryReader.h
@@ -32,6 +32,7 @@
 
 #include "FileReader.h"
 #include "MemoryBuffer.h"
+#include "os-dependent.h"
 
 namespace MPTV
 {
diff --git a/src/lib/tsreader/MemorySink.cpp b/src/lib/tsreader/MemorySink.cpp
index dafef56..af8b74c 100644
--- a/src/lib/tsreader/MemorySink.cpp
+++ b/src/lib/tsreader/MemorySink.cpp
@@ -84,7 +84,7 @@ void CMemorySink::addData(unsigned char* data, size_t dataSize, struct timeval U
     return;
   }
 
-  P8PLATFORM::CLockObject BufferLock(m_BufferLock);
+  std::lock_guard<std::mutex> BufferLock(m_BufferLock);
 
   m_bReEntrant = true;
   m_buffer.PutBuffer(data, dataSize);
diff --git a/src/lib/tsreader/MemorySink.h b/src/lib/tsreader/MemorySink.h
index cc0f3c8..22d91c6 100644
--- a/src/lib/tsreader/MemorySink.h
+++ b/src/lib/tsreader/MemorySink.h
@@ -35,7 +35,7 @@
 #endif
 
 #include "MemoryBuffer.h"
-#include "p8-platform/threads/mutex.h"
+#include <mutex>
 
 class CMemorySink: public MediaSink
 {
@@ -57,7 +57,7 @@ class CMemorySink: public MediaSink
   private: // redefined virtual functions:
     virtual Boolean continuePlaying();
 
-		P8PLATFORM::CMutex m_BufferLock;
+		std::mutex m_BufferLock;
     unsigned char* m_pSubmitBuffer;
     int   m_iSubmitBufferPos;
     bool  m_bReEntrant;
diff --git a/src/lib/tsreader/MepoRTSPClient.cpp b/src/lib/tsreader/MepoRTSPClient.cpp
index ccd6761..688ae84 100644
--- a/src/lib/tsreader/MepoRTSPClient.cpp
+++ b/src/lib/tsreader/MepoRTSPClient.cpp
@@ -54,7 +54,7 @@ CRTSPClient::CRTSPClient()
   m_env = NULL;
   m_fDuration = 0.0f;
   m_url[0] = '\0';
-  m_bRunning = false;
+  m_running = false;
 }
 
 CRTSPClient::~CRTSPClient()
@@ -496,7 +496,9 @@ void CRTSPClient::StartBufferThread()
 
   if (!m_BufferThreadActive)
   {
-    CreateThread();
+    m_running = true;
+    m_thread = std::thread([&] { Process(); });
+
     m_BufferThreadActive = true;
   }
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::StartBufferThread done");
@@ -505,11 +507,12 @@ void CRTSPClient::StartBufferThread()
 void CRTSPClient::StopBufferThread()
 {
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::StopBufferThread");
-  m_bRunning = false;
+  m_running = false;
   if (!m_BufferThreadActive)
     return;
 
-  StopThread();
+  if (m_thread.joinable())
+    m_thread.join();
 
   m_BufferThreadActive = false;
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::StopBufferThread done");
@@ -539,25 +542,22 @@ void CRTSPClient::FillBuffer(unsigned long byteCount)
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::Fillbuffer...%d/%d\n", byteCount, m_buffer->Size() );
 }
 
-void *CRTSPClient::Process()
+void CRTSPClient::Process()
 {
   m_BufferThreadActive = true;
-  m_bRunning = true;
 
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient:: thread started");
 
-  while (m_env != NULL && !IsStopped())
+  while (m_env != NULL && m_running)
   {
     m_env->taskScheduler().doEventLoop();
-    if (m_bRunning == false)
+    if (m_running == false)
       break;
   }
 
   kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient:: thread stopped");
 
   m_BufferThreadActive = false;
-
-  return NULL;
 }
 
 void CRTSPClient::Continue()
@@ -582,8 +582,12 @@ bool CRTSPClient::Pause()
   if (m_ourClient != NULL && m_session != NULL)
   {
     kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::Pause() stopthread");
-    StopThread(10000);                    // Ambass : sometimes 100mS ( prev value ) is not enough and thread is not stopped.
-                                                 //          now stopping takes around 5 secs ?!?! why ????
+    // Ambass : sometimes 100mS ( prev value ) is not enough and thread is not stopped.
+    //          now stopping takes around 5 secs ?!?! why ????
+    m_running = false;
+    if (m_thread.joinable())
+      m_thread.join();
+
     kodi::Log(ADDON_LOG_DEBUG, "CRTSPClient::Pause() thread stopped");
     RTSPClient* rtspClient=(RTSPClient*)m_ourClient;
     rtspClient->pauseMediaSession(*m_session);
diff --git a/src/lib/tsreader/MepoRTSPClient.h b/src/lib/tsreader/MepoRTSPClient.h
index bd6e578..9bb0421 100644
--- a/src/lib/tsreader/MepoRTSPClient.h
+++ b/src/lib/tsreader/MepoRTSPClient.h
@@ -31,7 +31,8 @@
 
 #ifdef LIVE555
 
-#include "p8-platform/threads/threads.h"
+#include <atomic>
+#include <thread>
 #include "lib/tsreader/MemoryBuffer.h"
 
 #include "liveMedia.hh"
@@ -41,7 +42,7 @@
 
 #define RTSP_URL_BUFFERSIZE 2048
 
-class CRTSPClient: public P8PLATFORM::CThread
+class CRTSPClient
 {
 public:
   CRTSPClient();
@@ -101,7 +102,7 @@ class CRTSPClient: public P8PLATFORM::CThread
 
   // Thread
 private:
-  virtual void *Process(void);
+  void Process();
   void StartBufferThread();
   void StopBufferThread();
   bool m_BufferThreadActive;
@@ -113,5 +114,8 @@ class CRTSPClient: public P8PLATFORM::CThread
   bool m_bRunning;
   bool m_bPaused;
   char m_outFileName[1000];
+
+  std::atomic<bool> m_running = {false};
+  std::thread m_thread;
 };
 #endif //LIVE555
diff --git a/src/lib/tsreader/MultiFileReader.cpp b/src/lib/tsreader/MultiFileReader.cpp
index 21fd7b2..5106418 100644
--- a/src/lib/tsreader/MultiFileReader.cpp
+++ b/src/lib/tsreader/MultiFileReader.cpp
@@ -35,17 +35,16 @@
 #include "MultiFileReader.h"
 #include <kodi/General.h> //for kodi::Log
 #include <kodi/Filesystem.h>
+#include <kodi/tools/EndTime.h>
 #include "TSDebug.h"
 #include <string>
 #include "utils.h"
 #include <algorithm>
-#include "p8-platform/threads/threads.h"
 #include <inttypes.h>
+#include "os-dependent.h"
 
 #include <thread>
 
-using namespace P8PLATFORM;
-
 //Maximum time in msec to wait for the buffer file to become available - Needed for DVB radio (this sometimes takes some time)
 #define MAX_BUFFER_TIMEOUT 1500
 
@@ -121,12 +120,12 @@ namespace MPTV
         if (RefreshTSBufferFile() == S_FALSE)
         {
             // For radio the buffer sometimes needs some time to become available, so wait and try it more than once
-            P8PLATFORM::CTimeout timeout(MAX_BUFFER_TIMEOUT);
+            kodi::tools::CEndTime timeout(MAX_BUFFER_TIMEOUT);
 
             do
             {
                 std::this_thread::sleep_for(std::chrono::milliseconds(100));
-                if (timeout.TimeLeft() == 0)
+                if (timeout.MillisLeft() == 0)
                 {
                     kodi::Log(ADDON_LOG_ERROR, "MultiFileReader: timed out while waiting for buffer file to become available");
                     kodi::QueueNotification(QUEUE_ERROR, "", "Time out while waiting for buffer file");
diff --git a/src/os-dependent.h b/src/os-dependent.h
index cdc6980..28c162c 100644
--- a/src/os-dependent.h
+++ b/src/os-dependent.h
@@ -11,6 +11,13 @@
 
 #if (defined(_WIN32) || defined(_WIN64))
 
+#include <wchar.h>
+
+/* Handling of 2-byte Windows wchar strings */
+#define WcsLen wcslen
+#define WcsToMbs wcstombs
+typedef wchar_t Wchar_t; /* sizeof(wchar_t) = 2 bytes on Windows */
+
 #ifndef _SSIZE_T_DEFINED
 #ifdef  _WIN64
 typedef __int64    ssize_t;
@@ -20,20 +27,108 @@ typedef _W64 int   ssize_t;
 #define _SSIZE_T_DEFINED
 #endif
 
+/* Prevent deprecation warnings */
+#define strnicmp _strnicmp
+
+#define PATH_SEPARATOR_CHAR '\\'
+
 #else
 
 #if (defined(TARGET_LINUX) || defined(TARGET_DARWIN))
 #include <sys/types.h>
 #include <chrono>
 #include <cstring>
+
+#define strnicmp(X,Y,N) strncasecmp(X,Y,N)
+
 inline unsigned long long GetTickCount64(void)
 {
   auto now = std::chrono::steady_clock::now();
   return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
 };
+
+#define PATH_SEPARATOR_CHAR '/'
+
+#if defined(__APPLE__)
+// for HRESULT
+#include <CoreFoundation/CFPlugInCOM.h>
+#endif
+
+/* Handling of 2-byte Windows wchar strings on non-Windows targets
+ * Used by The MediaPortal and ForTheRecord pvr addons
+ */
+typedef uint16_t Wchar_t; /* sizeof(wchar_t) = 4 bytes on Linux, but the MediaPortal buffer files have 2-byte wchars */
+
+/* This is a replacement of the Windows wcslen() function which assumes that
+ * wchar_t is a 2-byte character.
+ * It is used for processing Windows wchar strings
+ */
+inline size_t WcsLen(const Wchar_t *str)
+{
+  const unsigned short *eos = (const unsigned short*)str;
+  while( *eos++ ) ;
+  return( (size_t)(eos - (const unsigned short*)str) -1);
+};
+
+/* This is a replacement of the Windows wcstombs() function which assumes that
+ * wchar_t is a 2-byte character.
+ * It is used for processing Windows wchar strings
+ */
+inline size_t WcsToMbs(char *s, const Wchar_t *w, size_t n)
+{
+  size_t i = 0;
+  const unsigned short *wc = (const unsigned short*) w;
+  while(wc[i] && (i < n))
+  {
+    s[i] = wc[i];
+    ++i;
+  }
+  if (i < n) s[i] = '\0';
+
+  return (i);
+};
+
 #endif /* TARGET_LINUX || TARGET_DARWIN */
 
 #endif
 
+typedef long LONG;
+#if !defined(__APPLE__)
+typedef LONG HRESULT;
+#endif
+
+#ifndef FAILED
+#define FAILED(Status) ((HRESULT)(Status)<0)
+#endif
+
+#ifndef SUCCEEDED
+#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
+#endif
+
+#define _FILE_OFFSET_BITS 64
+#define FILE_BEGIN              0
+#define FILE_CURRENT            1
+#define FILE_END                2
+
+#ifndef S_OK
+#define S_OK           0L
+#endif
+
+#ifndef S_FALSE
+#define S_FALSE        1L
+#endif
+
+// Error codes
+#define ERROR_FILENAME_EXCED_RANGE 206L
+#define ERROR_INVALID_NAME         123L
+
+#ifndef E_OUTOFMEMORY
+#define E_OUTOFMEMORY              0x8007000EL
+#endif
+
+#ifndef E_FAIL
+#define E_FAIL                     0x8004005EL
+#endif
+
 // Additional typedefs
 typedef uint8_t byte;
diff --git a/src/pvrclient-mediaportal.cpp b/src/pvrclient-mediaportal.cpp
index 851b940..c1052e3 100644
--- a/src/pvrclient-mediaportal.cpp
+++ b/src/pvrclient-mediaportal.cpp
@@ -28,8 +28,6 @@
 #include <kodi/General.h>
 #include <kodi/Filesystem.h>
 
-#include <thread>
-
 using namespace kodi::tools;
 using namespace std;
 using namespace MPTV;
@@ -70,7 +68,6 @@ cPVRClientMediaPortal::cPVRClientMediaPortal(KODI_HANDLE instance, const std::st
   m_BackendTime            = 0;
   m_tsreader               = NULL;
   m_genretable             = NULL;
-  m_iLastRecordingUpdate   = 0;
   m_signalStateCounter     = 0;
   m_iSignal                = 0;
   m_iSNR                   = 0;
@@ -99,7 +96,7 @@ string cPVRClientMediaPortal::SendCommand(const char* command)
 
 string cPVRClientMediaPortal::SendCommand(const string& command)
 {
-  P8PLATFORM::CLockObject critsec(m_mutex);
+  std::lock_guard<std::mutex> critsec(m_mutex);
 
   if ( !m_tcpclient->send(command) )
   {
@@ -174,10 +171,10 @@ ADDON_STATUS cPVRClientMediaPortal::TryConnect()
     case PVR_CONNECTION_STATE_SERVER_UNREACHABLE:
       kodi::Log(ADDON_LOG_ERROR, "Could not connect to MediaPortal TV Server backend.");
       // Start background thread for connecting to the backend
-      if (!IsRunning())
+      if (!m_running)
       {
-        kodi::Log(ADDON_LOG_INFO, "Waiting for a connection in the background.");
-        CreateThread();
+        m_running = true;
+        m_thread = std::thread([&] { Process(); });
       }
       return ADDON_STATUS_LOST_CONNECTION;
     case PVR_CONNECTION_STATE_CONNECTING:
@@ -190,7 +187,7 @@ ADDON_STATUS cPVRClientMediaPortal::TryConnect()
 
 PVR_CONNECTION_STATE cPVRClientMediaPortal::Connect(bool updateConnectionState)
 {
-  P8PLATFORM::CLockObject critsec(m_connectionMutex);
+  std::lock_guard<std::mutex> critsec(m_connectionMutex);
 
   string result;
 
@@ -317,9 +314,11 @@ void cPVRClientMediaPortal::Disconnect()
 
   kodi::Log(ADDON_LOG_INFO, "Disconnect");
 
-  if (IsRunning())
+  if (m_running)
   {
-    StopThread(1000);
+    m_running = false;
+    if (m_thread.joinable())
+      m_thread.join();
   }
 
   if (m_tcpclient->is_valid() && m_bTimeShiftStarted)
@@ -361,14 +360,14 @@ bool cPVRClientMediaPortal::IsUp()
   }
 }
 
-void* cPVRClientMediaPortal::Process(void)
+void cPVRClientMediaPortal::Process()
 {
   kodi::Log(ADDON_LOG_DEBUG, "Background thread started.");
 
   bool keepWaiting = true;
   PVR_CONNECTION_STATE state;
 
-  while (!IsStopped() && keepWaiting)
+  while (m_running && keepWaiting)
   {
     state = Connect(false);
 
@@ -396,8 +395,6 @@ void* cPVRClientMediaPortal::Process(void)
   SetConnectionState(state);
 
   kodi::Log(ADDON_LOG_DEBUG, "Background thread finished.");
-
-  return NULL;
 }
 
 
@@ -1188,7 +1185,7 @@ PVR_ERROR cPVRClientMediaPortal::GetRecordings(bool deleted, kodi::addon::PVRRec
     }
   }
 
-  m_iLastRecordingUpdate = P8PLATFORM::GetTimeMs();
+  m_iLastRecordingUpdate = std::chrono::system_clock::now();
 
   return PVR_ERROR_NO_ERROR;
 }
@@ -1383,7 +1380,7 @@ PVR_ERROR cPVRClientMediaPortal::GetTimers(kodi::addon::PVRTimersResultSet& resu
     }
   }
 
-  if ( P8PLATFORM::GetTimeMs() >  m_iLastRecordingUpdate + 15000)
+  if ( std::chrono::system_clock::now() >  m_iLastRecordingUpdate + std::chrono::milliseconds(15000))
   {
     kodi::addon::CInstancePVRClient::TriggerRecordingUpdate();
   }
diff --git a/src/pvrclient-mediaportal.h b/src/pvrclient-mediaportal.h
index 3087634..e5da832 100644
--- a/src/pvrclient-mediaportal.h
+++ b/src/pvrclient-mediaportal.h
@@ -7,6 +7,10 @@
 
 #pragma once
 
+#include <atomic>
+#include <chrono>
+#include <mutex>
+#include <thread>
 #include <vector>
 
 /* Master defines for client control */
@@ -17,8 +21,6 @@
 #include "Cards.h"
 #include "epg.h"
 #include "channels.h"
-#include "p8-platform/threads/mutex.h"
-#include "p8-platform/threads/threads.h"
 
 /* Use a forward declaration here. Including RTSPClient.h via TSReader.h at this point gives compile errors */
 namespace MPTV
@@ -28,9 +30,7 @@ namespace MPTV
 class cRecording;
 
 class ATTRIBUTE_HIDDEN cPVRClientMediaPortal
-  : public kodi::addon::CInstancePVRClient,
-    public P8PLATFORM::PreventCopy,
-    public P8PLATFORM::CThread
+  : public kodi::addon::CInstancePVRClient
 {
 public:
   /* Class interface */
@@ -110,7 +110,7 @@ class ATTRIBUTE_HIDDEN cPVRClientMediaPortal
 
 private:
   /* TVServerKodi Listening Thread */
-  void* Process(void);
+  void Process();
   PVR_CONNECTION_STATE Connect(bool updateConnectionState = true);
 
   void LoadGenreTable(void);
@@ -134,9 +134,9 @@ class ATTRIBUTE_HIDDEN cPVRClientMediaPortal
   time_t                  m_BackendTime;
   CCards                  m_cCards;
   CGenreTable*            m_genretable;
-  P8PLATFORM::CMutex      m_mutex;
-  P8PLATFORM::CMutex      m_connectionMutex;
-  int64_t                 m_iLastRecordingUpdate;
+  std::mutex              m_mutex;
+  std::mutex              m_connectionMutex;
+  std::chrono::system_clock::time_point m_iLastRecordingUpdate;
   MPTV::CTsReader*        m_tsreader;
   std::map<int,cChannel>  m_channels;
   int                     m_signalStateCounter;
@@ -145,6 +145,9 @@ class ATTRIBUTE_HIDDEN cPVRClientMediaPortal
 
   cRecording*             m_lastSelectedRecording;
 
+  std::atomic<bool> m_running = {false};
+  std::thread m_thread;
+
   //Used for TV Server communication:
   std::string SendCommand(const char* command);
   std::string SendCommand(const std::string& command);
